package com.apes.scm.pur.priceChange;

import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.model.InventoryVo;
import com.apes.scm.account.account.repository.InventoryBatchRepository;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.invoice.model.InvoiceItem;
import com.apes.scm.invoice.service.InvoiceService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.rbac.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：采购变价单服务
 *
 * @author HuJianlin
 * @create 2018-06-27 11:35
 */
@Service("priceChangeService")
public class PriceChangeService extends DomainService {

    @Autowired
    PriceChangeRepository priceChangeRepository;
    @Autowired
    PriceChangeItemRepository priceChangeItemRepository;
    @Autowired
    ProductAccountService productAccountService;
    @Autowired
    LedgerService ledgerService;
    @Autowired
    InventoryBatchRepository inventoryBatchRepository;
    @Autowired
    InvoiceService invoiceService;
    @Autowired
    InventoryService inventoryService;
    @Autowired
    BusinessAttributeValueRepository businessAttributeValueRepository;


    /**
     * 功能：创建采购变价单
     *
     * @param request
     * @return
     */
    public PriceChange create(SimpleRequest request) {
        PriceChange priceChange = request.getO(PriceChange.class);
        priceChange.setState("sent");
        priceChange.setCreateDate(new Date());
        if (priceChange.getCreateUid() == null) priceChange.setCreateUid(request.getPerson());
        if (priceChange.getCreateUid() != null) {
            priceChange.setCreator(priceChange.getCreateUid().getId());
            priceChange.setUserId(SpringManager.getBean(UserRepository.class).findOne(JpaDsl.toCriteriaByEq("person.id", priceChange.getCreateUid().getId())).get().getId() + "");
        }
        priceChange.computeAmt();   // 合计
        return priceChangeRepository.saveAndFlush(priceChange);
    }

    /**
     * 功能：创建采购变价单
     *
     * @param request
     * @return
     */
    public PriceChange update(SimpleRequest request) {
        checkData(request);

        PriceChange priceChange = request.getO(PriceChange.class);
        priceChange.setUpdateDate(new Date());
        priceChange.computeAmt();
        return priceChangeRepository.saveAndFlush(priceChange);
    }

    public PriceChange checkData(SimpleRequest request){
        PriceChange sourcePriceChange = request.getO(PriceChange.class);
        PriceChange priceChange = priceChangeRepository.findOne(sourcePriceChange.getId());
        if (priceChange == null) throw new RuntimeException("采购变价单：" + sourcePriceChange.getId() + " 在系统中不存在。");
        if (priceChange.getApproveDate() != null) throw new RuntimeException("采购变价单：" + sourcePriceChange.getId() + " 在系统中已审批。");

        return sourcePriceChange;
    }

    public String delete(SimpleRequest request) {
        checkData(request);

        PriceChange priceChange = request.getO(PriceChange.class);
        priceChange.setState("delete");
        priceChange.setDeleteDate(new Date());
        priceChange.setDeleteUid(request.getPerson());
        priceChangeRepository.saveAndFlush(priceChange);
        return "删除成功！";
    }

    /**
     * 功能：审批采购变价单
     *
     * @param request
     * @return
     */
    public PriceChange approve(SimpleRequest request) {
        PriceChange priceChange = checkData(request);

        //根据批次的当前状态分配变价数量到库存、销售或损益
        priceChange = evaluation(priceChange);

        //保存新状态
        priceChange.setState("done");
        priceChange.setApproveDate(new Date());
        if (priceChange.getApproveUid() == null) priceChange.setApproveUid(getPerson(request));
        if (priceChange.getApproveUid() != null) {
            priceChange.setCreator(priceChange.getApproveUid() .getId());
            priceChange.setUserId(SpringManager.getBean(UserRepository.class).findOne(JpaDsl.toCriteriaByEq("person.id", priceChange.getApproveUid() .getId())).get().getId() + "");
        }
        priceChange = priceChangeRepository.saveAndFlush(priceChange);

        //创建采购账单
        createInvoice(priceChange);

        return priceChange;
    }

    /**
     * 采购变价单.价值评估（根据批次的当前状态分配变价数量到库存、销售或损益）
     * @param priceChange
     * @return
     */
    private PriceChange evaluation(PriceChange priceChange){
       priceChange.getPriceChangeItems().stream().forEach(item -> {
            InventoryVo inventoryVo = new InventoryVo();
            List<InventoryBatch> list = new ArrayList();
            list.add(item.getOldBatch());
            inventoryVo.setInInventories(list);
            inventoryVo.setCompany(priceChange.getCompany());
            inventoryVo.setSupplier(priceChange.getSupplier());
//            inventoryVo.setDept(priceChange.getDept());
//            inventoryVo.setContract(priceChange.getContract());
            inventoryVo.setInventoryMode(priceChange.getCooperation().getInventoryMode());
            inventoryVo.setPriceChangeMode(priceChange.getPriceChangeMode());
            inventoryVo.setProduct(item.getProduct());
            inventoryVo.setUom(item.getUom());
            inventoryVo.setTax(item.getTax());
            inventoryVo.setQty(item.getProductUomQty());
            inventoryVo.setInDate(new Date());
            inventoryVo.setTaxCostPrice(item.getNewPrice());

            inventoryVo = inventoryService.priceChangeEvaluate(inventoryVo);

            item.setNewBatch(inventoryVo.getOutInventoryBatch());
            item.setChangeBalanceQty(inventoryVo.getOutInventoryBatch().getBalanceQty());
            item.setChangeSalesQty(inventoryVo.getOutInventoryBatch().getSalesQty());
            item.setChangeProfitLossQty(-inventoryVo.getOutInventoryBatch().getProfitAndLossQty());
       });

        return priceChange;
    }

    /**
     * 构造采购账单
     * @param priceChange
     * @return
     */
    public void createInvoice(PriceChange priceChange) {
        priceChange.getPriceChangeItems().stream().collect(Collectors.groupingBy(item -> item.getNewBatch().getCompany())).forEach((k,v)->{
            createInvoice(v, k);
        });
    }

    /**
     * 构造采购账单
     * @param priceChangeItems
     * @return
     */
    private Invoice createInvoice(List<PriceChangeItem> priceChangeItems, PartyRole company){
        PriceChange priceChange = priceChangeItems.get(0).getPriceChange();
        String inventoryMode = priceChange.getCooperation().getInventoryMode();
        Set items = new HashSet();
        double amtTotal = 0;
        double amtTaxTotal = 0;
        double amtConsignBalance = 0;

        for (PriceChangeItem priceChangeItem : priceChangeItems){
            double qty = 0;
            double amt = 0;
            double amtTax = 0;
            double priceMargin = priceChangeItem.getNewPrice() - priceChangeItem.getOldPrice();
            if (inventoryMode.equals(InventoryMode.IM_OWN)){
                qty = priceChangeItem.getProductUomQty();
                amt = priceChangeItem.getAmtWithTax();
                amtTax = priceChangeItem.getTaxAmt();
            }else if (inventoryMode.equals(InventoryMode.IM_CONSIGN)){
                qty = priceChangeItem.getChangeSalesQty();
                amt = priceChangeItem.getAmtWithTax()*qty/priceChangeItem.getProductUomQty();
                amtTax = priceChangeItem.getTaxAmt()*qty/priceChangeItem.getProductUomQty();
                amtConsignBalance += priceChangeItem.getChangeBalanceQty()*priceMargin;
            }
            if (qty>0){
                InvoiceItem item = new InvoiceItem();
                item.setCompany(company);
                item.setProduct(priceChangeItem.getProduct());
                item.setPriceUnit(priceMargin);
                item.setQty(qty);
                item.setUom(priceChangeItem.getUom());
                item.setTax(priceChangeItem.getTax());
                item.setAmtTax(amtTax);
                item.setPriceSubtotal(amt);
                item.setAmtUntaxed(amt - amtTax);
                item.setOriginBusinessType(priceChange.getInnerBusinessType());
                item.setOrigin(priceChange.getId());
                item.setOriginItemId(String.valueOf(priceChangeItem.getId()));
                item.setSourceItemId(String.valueOf(priceChangeItem.getId()));
                item.setVersion(0);
                items.add(item);
                amtTotal += item.getPriceSubtotal();
                amtTaxTotal += item.getAmtTax();
            }
        }
        //寄售调库存部分的金额不生成账单，写入 账款.暂估
        if (amtConsignBalance > 0){
            ledgerService.charge(company, priceChangeItems.get(0).getNewBatch().getDept(), priceChange.getSupplier(),
                    priceChange.getCooperation().getInventoryMode(), priceChange.getCooperation().getAccountingMethod(),
                    priceChange.getInnerBusinessKey(), priceChange.getInnerBusinessType(),
                    priceChange.getApproveDate(), "current_provisional", amtConsignBalance);
        }
        // 账单明细有数据则生成账单并保存
        if (items.size()>0){
            Invoice invoice = new Invoice();
            invoice.setCompany(company);
            invoice.setPartner(priceChange.getSupplier());
            invoice.setDept(priceChangeItems.get(0).getNewBatch().getDept());
//            invoice.setContract(priceChange.getContract());
            invoice.setInventoryMode(priceChange.getCooperation().getInventoryMode());
            invoice.setAccountingMethod(priceChange.getCooperation().getAccountingMethod());
            invoice.setOriginBusinessType(priceChange.getInnerBusinessType());
            invoice.setOrigin(priceChange.getId());
            invoice.setSourceBusinessType(priceChange.getInnerBusinessType());
            invoice.setSource(priceChange.getId());
            invoice.setAmtTotal(amtTotal);
            invoice.setAmtTax(amtTaxTotal);
            invoice.setAmtUntaxed(amtTotal - amtTaxTotal);
            invoice.setInvoiceItems(items);
            invoice.setCreator(priceChange.getApproveUid().getId());
            invoice = invoiceService.save(invoice);
            return invoice;
        }else{
            return null;
        }
    }

}
